package com.opennews.openplatform

import com.opennews.openplatform.constants.HttpRequestContentType
import groovy.transform.CompileStatic
import io.micronaut.http.HttpRequest
import io.micronaut.http.client.HttpClient
import io.micronaut.http.uri.UriBuilder

/**
 * Follows official guide and provides external REST resource calling.
 * https://guides.grails.org/grails-micronaut-http/guide/index.html
 */
@CompileStatic
class HttpRequestHelper {
    /**
     * Makes http get request.
     * @param baseUrl: The root of uri. Example: http://192.168.1.240:8080.
     * @param url: String of rest of url. Example: /smart-farm-api/smsCode/sendAuthCode.
     * @param headers: Map instance which contains http request header data.
     * @param params: Map instance which contains each url query string.
     * @param bodyType: The data type will returned from remote. Like String, Map and etc.
     * @return: Which is specified by bodyType.
     */
    static <T> T get(String baseUrl, String url, Map<CharSequence, CharSequence> headers, Map<String, ?> params, Class<T> bodyType) {
        // Prepares url builder based on provided params.
        def uriBuilder = UriBuilder.of(url)

        params?.keySet().each {
            uriBuilder.queryParam(it, params.get(it))
        }

        // Creates client with base url.
        def client = HttpClient.create(baseUrl.toURL())

        // Creates http get request.
        def request = HttpRequest.GET(uriBuilder.build()).headers(headers).contentType(HttpRequestContentType.JSON)

        // Makes request and gets response.
        def response = client.toBlocking().exchange(request, bodyType)

        // Returns response body as result.
        return response.body()
    }

    /**
     * Makes http get request and gets Map type of response body.
     * @param baseUrl: The root of uri. Example: http://192.168.1.240:8080.
     * @param url: String of rest of url. Example: /smart-farm-api/smsCode/sendAuthCode.
     * @param headers: Map instance which contains http request header data.
     * @param params: Map instance which contains each url query string.
     * @return: Map instance of response body.
     */
    static Map get(String baseUrl, String url, Map<CharSequence, CharSequence> headers, Map<String, ?> params) {
        return get(baseUrl, url, headers, params, Map)
    }

    /**
     * Makes http post request.
     * @param baseUrl: The root of uri. Example: http://192.168.1.240:8080.
     * @param url: String of rest of url. Example: /smart-farm-api/smsCode/sendAuthCode.
     * @param headers: Map instance which contains http request header data.
     * @param body: Map instance which contains http request body data.
     * @param bodyType: The data type will returned from remote. Like String, Map and etc.
     * @return: Which is specified by bodyType.
     */
    static <T> T post(String baseUrl, String url, Map<CharSequence, CharSequence> headers, T body, Class<T> bodyType) {
        // Defines body type based on T.
        //Class<T> bodyType

        // Creates client with base url.
        def client = HttpClient.create(baseUrl.toURL())

        // Creates http post request.
        def request = HttpRequest.POST(url, body).headers(headers).contentType(HttpRequestContentType.JSON)

        // Makes request and gets response.
        def response = client.toBlocking().exchange(request, bodyType)

        // Returns response body as result.
        return response.body()
    }

    /**
     * Makes http post request and gets Map type of response body.
     * @param baseUrl: The root of uri. Example: http://192.168.1.240:8080.
     * @param url: String of rest of url. Example: /smart-farm-api/smsCode/sendAuthCode.
     * @param headers: Map instance which contains http request header data.
     * @param body: Map instance which contains http request body data.
     * @return: Map instance of response body.
     */
    static Map post(String baseUrl, String url, Map<CharSequence, CharSequence> headers, Map body) {
        return post(baseUrl, url, headers, body, Map)
    }
}
